/* Hawk - An OSGI Based Test Framework
 *
 * Copyright (C) 2010 http://code.google.com/p/hawk-framework/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */
package org.hawk.gui.trees;

import java.util.ResourceBundle;

import org.hawk.gui.HawkWeb;
import org.hawk.gui.windows.MainWindow;
import org.hawk.gui.windows.StepWindow;

import org.hawk.core.model.Step;
import org.hawk.core.model.TestCase;

import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.data.Property.ValueChangeListener;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.ui.AbstractSelect;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Tree;

/**
 * This class is responsible to creates and handle the test session tree
 * 
 * @author Rodrigo Prestes Machado
 * @version November 15. 2009
 */
@SuppressWarnings("serial")
public class TestSessionTree extends CustomComponent implements Handler, ValueChangeListener {

	/** Test session tree attribute */
    private Tree tree;
    
    /** Caption property id */ 
    private static final Object CAPTION_PROPERTY = "caption";

    /** Creating context menu actions actions */ 
    private Action ADD_CASE;
    private Action ADD_STEP;
    private Action CONFIG;
    private Action DELETE;
    
    /** Grouping the context menu actions */ 
    private Action[] testSessionActions;
    private Action[] testCaseActions;
    private Action[] stepActions;

    /** Test session tree instance (singleton) */
    private static TestSessionTree instance;
    
    /** Localized System messages */
    private ResourceBundle messages;
    
    /**
     * Constructor
     */
    private TestSessionTree() {
		
    	// Recovering the system messages
        this.messages = HawkWeb.getMessages();
    	
    	// Tree with a few items
        tree = new Tree();
        tree.setImmediate(true);
        
        // Configuring the tree items id
        tree.addContainerProperty(CAPTION_PROPERTY, Object.class, null);
        tree.setItemCaptionMode(AbstractSelect.ITEM_CAPTION_MODE_ID);
        tree.setItemCaptionPropertyId(CAPTION_PROPERTY);
        
        // Adding the root node of the tree
        Object id = addItem(messages.getString("TestSessionTree.testSession"), null);
        tree.expandItem(id);
        
        // Creating context menu actions actions 
        ADD_CASE = new Action(messages.getString("TestSessionTree.addTestCase"));
        ADD_STEP = new Action(messages.getString("TestSessionTree.addStep"));
        CONFIG = new Action(messages.getString("TestSessionTree.configTestStep"));
        DELETE = new Action(messages.getString("TestSessionTree.remove"));
        
        // Grouping the context menu actions 
        testSessionActions = new Action[] { ADD_CASE  };
        testCaseActions = new Action[] { ADD_STEP, DELETE };
        stepActions = new Action[] { CONFIG, DELETE,  };
        
        // Adding listeners
        tree.addListener(this);
        tree.addActionHandler(this);
    }
    
    /**
     * Returns the unique instance of TestSessionTree object
     * 
     * @return An instance of TestSessionTree
     */
    public static TestSessionTree getInstance(){
    	if (instance == null)
    		instance = new TestSessionTree();
    	return instance;
    }

    /**
     * This method add or remove items depending of the action object
     */
    public void handleAction(Action action, Object sender, Object target) {
        if (action == DELETE) {
            tree.removeItem(target);
        } 
        else if (action == ADD_CASE) {
            // Add Test Case
            final Object id = addItem(new TestCase(), target);
            tree.expandItem(target);
            tree.setValue(id);
        }
        else if (action == ADD_STEP) {
            // Add Test Step
            final Object id = addItem(new Step(), target);
            tree.expandItem(target);
            tree.setValue(id);
        }
        else if (action == CONFIG) {
        	MainWindow mainWindow = MainWindow.getInstance();
        	
        	Item item = tree.getItem(target);
        	Property p = item.getItemProperty(CAPTION_PROPERTY);
        	Step step = (Step) p.getValue();
        	
        	StepWindow stepWindow = new StepWindow(step, messages);
        	
        	mainWindow.addWindow(stepWindow);
        }
    }

    /**
     * Add an item with specified caption and (optional) parent
     * 
     * @param  Caption The item caption
     * @param  Parent The (optional) parent item id
     * @return The created item's id
     */
    private Object addItem(Object caption, Object parent) {
    	// add item, let tree decide id
        final Object id = tree.addItem();
        // get the created item
        final Item item = tree.getItem(id);
        // set our "caption" property
        final Property p = item.getItemProperty(CAPTION_PROPERTY);
        p.setValue(caption);
        if (parent != null) {
            tree.setChildrenAllowed(parent, true);
            tree.setParent(id, parent);
            tree.setChildrenAllowed(id, false);
        }
        return id;
    }

	/**
	 * Returns the context menu 
	 */
    public Action[] getActions(Object target, Object sender) {
		String caption = tree.getItemCaption(target);
		if(caption.equals(messages.getString("TestSessionTree.testSession")))
			return testSessionActions;
		else if (caption.equals("Test Case"))
			return testCaseActions;
		else
			return stepActions;
	}
	
	/**
	 * Returns the test session tree
	 * 
	 * @return Tree tree : A test session tree object
	 */
	public Tree getTree() {
		return tree;
	}
	
	/**
	 * We are not using this method in test session tree
	 */
	@Deprecated
	public void valueChange(ValueChangeEvent event) {
		// TODO implement the value change method in TestSessionTree class
	}	
}